package com.remainder.sdk.export.service.impl;

import java.util.Date;
import java.util.Objects;
import java.util.UUID;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.remainder.common.core.exception.BusinessException;
import com.remainder.common.core.utils.StringUtils;
import com.remainder.sdk.export.config.ExportLogConfig;
import com.remainder.sdk.export.domain.ExportLog;
import com.remainder.sdk.export.enums.ExportLogStatusEnum;
import com.remainder.sdk.export.mapper.ExportLogMapper;

/**
 * 导出日志Service业务层处理
 *
 * @author qiaomignzhi
 * @date 2023-06-13
 */
public class ExportLogService {

    private final ThreadLocal<ExportLog> threadLocal = new ThreadLocal<>();
    private final ExportLogMapper exportLogMapper;

    public ExportLogService(ExportLogMapper exportLogMapper) {
        this.exportLogMapper = exportLogMapper;
    }

    /**
     * 创建导出任务
     *
     * @param config
     *            导出批次任务数
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    protected String caeateExportLog(ExportLogConfig config) {
        if (Objects.isNull(config.getOperatorUserId()) || Objects.isNull(config.getExportFileSourceEnum())
            || StringUtils.isEmpty(config.getOperatorName())) {
            throw new BusinessException("ExportLogService.caeateExportLog param error");
        }
        threadLocal.remove();
        ExportLog exportLog = ExportLog.builder().batchNumber(UUID.randomUUID().toString().replace("-", ""))
            .operatorId(config.getOperatorUserId()).operatorName(config.getOperatorName())
            .exportSource(config.getExportFileSourceEnum().getCode()).total(config.getTotal())
            .batchSize(config.getTotal()).remainBatch(0).status(ExportLogStatusEnum.NEW.getCode())
            .operatingSource(config.getOperatingSource().getCode()).gmtCreate(new Date()).build();
        exportLogMapper.insertExportLog(exportLog);
        threadLocal.set(exportLog);

        return exportLog.getBatchNumber();
    }

    /**
     * 执行批次任务
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    protected void executorExportSubTask() {
        ExportLog exportLog = checkExportTask();
        exportLog.setRemainBatch(exportLog.getRemainBatch() + 1);
        exportLog.setGmtModified(new Date());
        exportLog.setStatus(ExportLogStatusEnum.PROCESSING.getCode());
        exportLogMapper.updateExportLog(exportLog);
    }

    /**
     * 导出任务完结
     *
     * @param exportType
     *            导出任务类型
     * @param exportDetails
     *            导出任务详情
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    protected void exportLogFinally(String exportType, String exportDetails) {
        ExportLog exportLog = checkExportTask();
        threadLocal.remove();
        exportLog.setExportType(Integer.parseInt(exportType));
        exportLog.setExportDetails(exportDetails);
        exportLog.setStatus(ExportLogStatusEnum.FINISH.getCode());
        exportLog.setGmtModified(new Date());
        exportLogMapper.updateExportLog(exportLog);
    }

    /**
     * 导出任务状态更新（新事务）
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    protected void failUpdate() {
        ExportLog exportLog = checkExportTask();
        exportLog.setStatus(ExportLogStatusEnum.FAIL.getCode());
        exportLog.setGmtModified(new Date());
        exportLogMapper.updateExportLog(exportLog);
    }

    /**
     * 检查导出任务
     *
     * @return 结果
     */
    private ExportLog checkExportTask() {
        ExportLog exportLog = threadLocal.get();
        if (Objects.isNull(exportLog)) {
            throw new BusinessException("ExportLogService.checkExportTask uninitialized export task");
        }
        return exportLog;
    }
}
